//------------------------------------------------------------------------------
// Fichiers d'ent�te utilis�s
//------------------------------------------------------------------------------
#include "OutlineClosingOperator.hpp"
#include "Outline.hpp"
#include "Orientation.hpp"
#include "iostream"
#include "Tools/Logger.hpp"

//------------------------------------------------------------------------------
// Définition de constantes
//------------------------------------------------------------------------------

namespace ImageAnalysis
{

	//----------------------------------------------------------------------
	// Constructeur
	//----------------------------------------------------------------------
	OutlineClosingOperator::OutlineClosingOperator( Gradiant* _gradiant, OutlineContainer * _outlineContainer, int _windowSize ):
	outlineContainer(_outlineContainer),
	gradiant(_gradiant),
	windowSize(_windowSize)
	{

	}

	//----------------------------------------------------------------------
	// Destructeur
	//----------------------------------------------------------------------
	OutlineClosingOperator::~OutlineClosingOperator( )
	{

	}

	//----------------------------------------------------------------------
	//
	//----------------------------------------------------------------------
	void OutlineClosingOperator::Process( )
	{
        	OutlineContainer::TOutlineContainerIterator outlineIterator;
		outlineIterator = outlineContainer->GetStartOutline();		
		int cnt = 0;
		std::cout<<windowSize<<std::endl;
		int holes[40];
		while (outlineIterator!=outlineContainer->GetEndOutline())
        	{
	    		//std::cout<<"1er while"<<std::endl;
            		Outline::TOutlineIterator pixelIterator;
            		pixelIterator = (*outlineIterator)->GetStartIndex();
            		//on r�up�e la direction du gradient en ce point
            		Orientation::TDirection gradiantDirection = Orientation::GetOrthogonalDirection(gradiant->GetGradiantApproximatedOrientation(*pixelIterator));

            		//on cherche si l'extr�it�d'un contour est proche de ce point en suivant la crete
            		Layer::PixelNeighborHood neighbors =  gradiant->GetDirectPixelNeighborHood(*pixelIterator);
            		int interestingneighbor = neighbors.index[gradiantDirection];
            		bool boucleSuivi = true;
            		holes[0] = interestingneighbor;
            		int nbTimes =0;
            		bool mergeDirection;
            		while (boucleSuivi)
            		{
                		bool onTourne = true;
                		OutlineContainer::TOutlineContainerIterator outlineIterator2 = outlineContainer->GetStartOutline();
                		while(onTourne)
                		{
                    			if (outlineIterator2 == outlineContainer->GetEndOutline())
                    			{
                        			onTourne = false;
                    			}
                    			else
                    			{
                        			Outline::TOutlineIterator pixelIteratorDeb = (*outlineIterator2)->GetStartIndex();

                        			Outline::TOutlineIterator pixelIteratorFin = --(*outlineIterator2)->GetEndIndex();

                        			if(*pixelIteratorDeb==interestingneighbor)
                        			{
                            				onTourne = false;
                            				mergeDirection = false;
                        			}
                        			else if (((*outlineIterator2)->GetEndIndex()!=(*outlineIterator2)->GetStartIndex())&&(*pixelIteratorFin==interestingneighbor))
                        			{
                            				onTourne = false;
                            				mergeDirection = true;
							
                        			}
                        			else
                        			{
                            				++outlineIterator2;
                        			}
                    			}
                		}
                		if ( outlineIterator2 != outlineContainer->GetEndOutline())
                		{
                    			boucleSuivi = false;
                    			//ajout des trous �la fin du premier outline
                    			for(int i=nbTimes-1; i>=0; i--)
                    			{                        			
                        			(*outlineIterator2)->AddIndexAfterEnd(holes[i]);
                    			}
                    			//on v�ifie qu'on n'essaie pas de merger le contour avec lui-m�e
                    			if(outlineIterator != outlineIterator2)
                    			{                        			
						outlineContainer->MergeOutline( *outlineIterator2, *outlineIterator, mergeDirection?OutlineContainer::END1_START2:OutlineContainer::START1_START2 );
						OutlineContainer::TOutlineContainerIterator killer = outlineIterator;
						++outlineIterator;
						outlineContainer->RemoveOutline( killer );
                    			}
		    			else
		    			{
						++outlineIterator;
		    			}
					//std::cout<<"dans boucle"<<std::endl;
				}
				else if (nbTimes<windowSize)
				{
					//std::cout<<"dans elseif"<<std::endl;
					Orientation::TDirection gradiantDirection = Orientation::GetOrthogonalDirection(gradiant->GetGradiantApproximatedOrientation(interestingneighbor));
					Layer::PixelNeighborHood neighbors =  gradiant->GetDirectPixelNeighborHood(interestingneighbor);
					interestingneighbor = neighbors.index[gradiantDirection];
					nbTimes++;
					holes[nbTimes]=interestingneighbor;
				}
				else
				{
					boucleSuivi = false;
					++outlineIterator;
				}
				//std::cout<<"bientot fin"<<std::endl;
            		}
	   	//std::cout<<"bientot sortie"<<std::endl;
		cnt++;
        	}
	//delete [] holes;
	//std::cout<<"sortie"<<std::endl;
	}
	
}
